package handler;

import java.io.*;
import java.net.*;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.jdom2.*;

import org.jdom2.input.SAXBuilder;
import org.xml.sax.SAXException;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.util.Log;
/**
 * API permettant de telecharger les pochettes d'albums pour les albums qui n'en ont pas encore.
 * Pour que l'API fonctionne, il faut ajouter la librairie jdom au projet
 * @author Clement
 *
 */
public class APIAlbumCover {

	public APIAlbumCover() {
		
	}
	
	
	/**
	 * Methode appelee permettant de verifier la validite ou non du lien nous dirigeant vers la pochette de l'album.
	 * @param urlString: url de l'image
	 * @return
	 * @throws IOException
	 */
	private InputStream OpenHttpConnection(String urlString)
            throws IOException
            {
                InputStream in = null;
                int response = -1;

                URL url = new URL(urlString);
                URLConnection conn = url.openConnection();

                if (!(conn instanceof HttpURLConnection))                    
                    throw new IOException("Not an HTTP connection");

                try{
                    HttpURLConnection httpConn = (HttpURLConnection) conn;
                    httpConn.setAllowUserInteraction(false);
                    httpConn.setInstanceFollowRedirects(true);
                    httpConn.setRequestMethod("GET");
                    httpConn.connect();

                    response = httpConn.getResponseCode();                
                    if (response == HttpURLConnection.HTTP_OK) 
                    {
                        in = httpConn.getInputStream();                                
                    }                    
                }
                catch (Exception ex)
                {
                    throw new IOException("Error connecting");            
                }
                return in;    
    }
	
	/**
	 * getPochetteAlbum est la methode permettant de telecharger la pochette de l'album. Pour cela, il faut lui passer
	 * en parametre le nom de l'artiste ainsi que le nom de l'album.
	 * Cette methode necessite l'acces a internet. Car avec l'artiste et l'album on accede a une page internet (grace
	 * au site lastfm.fr). La connexion etablie, ce qui nous est renvoye est un fichier xml comportant diverses informations
	 * sur l'artiste et l'album. On enregistre ce fichier sur la carte SD. On peut ensuite parser ce fichier pour recuperer
	 * les donnees qui nous interessent. Dans la branche "album" il y a plusieurs images que l'on peut recuperer.
	 * On recupere alors la plus grande: "mega" qui se trouve sous la forme d'un lien URL. On recupere alors cette image
	 * que l'on passe en bitmap. Ensuite en fonction de si l'image est un JPG ou PNG on appelle la methode correspondante 
	 * pour la recuperer en tableau d'octets (byte): getBytesFromBitmapJPG ou getBytesFromBitmapPNG.
	 * 
	 * @param artist String
	 * @param album String
	 * @return Image en tableau d'octets
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws TransformerException
	 */
	public byte[] getPochetteAlbum(String artist, String album) throws IOException, ParserConfigurationException, SAXException, TransformerException {
		org.jdom2.Element racine;
		Document document = null;
		/**
		 * On fait en sorte que l'artiste et l'album soient au bon format pour le futur URL
		 * Des qu'il y a un espace, on le remplace par "%20" pour que le lien fonctionne correctement
		 */
		String[] monStringArtiste = artist.split("\\s");
		String resultArtiste = "";
		for(int x=0;x<monStringArtiste.length;x++){
			resultArtiste += monStringArtiste[x];
			if(x<monStringArtiste.length-1)
				resultArtiste += "%20";
		}
		
		String[] monStringAlbum = album.split("\\s");
		String resultAlbum = "";
		for(int x=0;x<monStringAlbum.length;x++){
			resultAlbum += monStringAlbum[x];
			if(x<monStringAlbum.length-1)
				resultAlbum += "%20";
		}
		
		/**
		 * Declaration du lien URL qui va recuperer le fichier xml grace a lastfm
		 */
		URL url = new URL("http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=98ddfa5cef756e5fb7106c7664085386&artist=" + resultArtiste + "&album=" + resultAlbum);
		URLConnection conn = url.openConnection();

		/**
		 * On recupere le fichier xml et on le parse
		 * Si il y a un probleme, alors on renvoie null ce qui permet a l'application de ne pas planter
		 * et de mettre une pochette par defaut pour l'album
		 */
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		org.w3c.dom.Document doc = null;
		SAXBuilder sxb = new SAXBuilder();
		File file;
		try{
			doc = builder.parse(conn.getInputStream());
			
			TransformerFactory myfactory = TransformerFactory.newInstance();
			Transformer xform = myfactory.newTransformer();
			
			File SDCardRoot = new File("/sdcard");
			file = new File(SDCardRoot,"file.xml");
			
			Result ok = new StreamResult(file.toURI().getPath());
			xform.transform(new DOMSource(doc), ok);
		}
		catch(Exception e){
			Log.v("Pas de pochette", "Pas de pochette pour cet album");
			return null;
		}
		
		try
	      {
	         document = sxb.build(file);
	      }
	      catch(Exception e){}
		
		/**
		 * On parcourt le fichier xml qui est parse.
		 * On regarde les "enfants" de "album" et lorsque l'on trouve "image" avec l'attribut "mega" correspondant a
		 * la plus grande image alors on recupere le lien de l'image se trouvant entre les balises <image size = "mega">
		 */
		racine = document.getRootElement();
		List listeImage = racine.getChildren("album");
		String picture = null;
		for (int i = 0; i < listeImage.size(); i++) {
			  Element Companyname = (Element) listeImage.get(i);
			  List column = Companyname.getChildren("image");
		  for (int j = 0; j < column.size(); j++) {
			  Element Employee = (Element) column.get(j);
			  String name = Employee.getAttribute("size").getValue();
			  if(name.equals("mega")){
				  System.out.println(Employee.getText());
				  picture = Employee.getText();
			  }
		  }
		}
		
		/**
		 * On teste si le lien nous dirigeant vers l'image est valide, si oui alors on appelle l'une des methodes permettant
		 * de convertir l'image en tableau d'octets, si non, on retourne null afin de quitter l'API et donc de mettre
		 * une pochette par defaut a l'album.
		 */
		Bitmap bitmap = null;
        InputStream in = null;
        try {
            in = OpenHttpConnection(picture);
            bitmap = BitmapFactory.decodeStream(in);
            in.close();
        } catch (IOException e1) {
            e1.printStackTrace();
            return null;
        }
		byte[] byte_img_data;
		Log.v("marche pas", picture);
		if((picture.substring(picture.length()-3)).equals("jpg")){
			byte_img_data = getBytesFromBitmapJPG(bitmap); 
			return byte_img_data;
		}
		else{
			if((picture.substring(picture.length()-3)).equals("png")){
				byte_img_data = getBytesFromBitmapPNG(bitmap);
				return byte_img_data;
			}
		}
	    
		return null;
	}
	
	/**
	 * Une image JPG l'on passe au format bitmap en parametre et qui nous est renvoye sous forme de tableau d'octets
	 * @param bitmap
	 * @return tableau de d'octets
	 */
	public byte[] getBytesFromBitmapJPG(Bitmap bitmap) {
	    ByteArrayOutputStream stream = new ByteArrayOutputStream();
	    bitmap.compress(CompressFormat.JPEG, 70, stream);
	    return stream.toByteArray();
	}
	
	/**
	 * Une image PNG l'on passe au format bitmap en parametre et qui nous est renvoye sous forme de tableau d'octets
	 * @param bitmap
	 * @return tableau d'octets
	 */
	public byte[] getBytesFromBitmapPNG(Bitmap bitmap) {
	    ByteArrayOutputStream stream = new ByteArrayOutputStream();
	    bitmap.compress(CompressFormat.PNG, 70, stream);
	    return stream.toByteArray();
	}
	
}
